package com.whales.lms.rms.scheduler;

import java.util.Date;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import com.whales.shared.exception.BaseException;

/**
 * 모니터링을 위한 Scheduler 제어 클래스
 * @author sw775.park
 */
@Component
public class SchedulerExecutor {
    @Inject 
    ThreadPoolTaskScheduler poolTaskScheduler;
    @Inject
    TaskScheduler taskScheduler;
    @Inject
    TaskFactory taskFactory;
    boolean shutdown;
//    @Value("#{contextProperties['mdw.scheduling.current.system']}")
    String currenSystem = "LOCAL";

    /**
     * Scheduler start
     * 
     * <p>※ Local server에서는 실행되지 않습니다.<br>
     *   테스트를 위해 실행되어야 한다면, 아래 return 부분을 주석처리 하시기 바랍니다.</p>
     */
    @PostConstruct
    public void start() throws Exception{
        //local server이면 실행 금지
        if(this.isLocalServer()){
            //테스트를 위해 Local server에서 실행되도록 하려면 해당 라인을 주석 처리한다.
//            return;
        }
        System.out.print(">> Start scheduler");

        List<Task> taskList = taskFactory.getTaskList();
        //Scheduler의 pool size를 설정 한다.
        this.setPoolSize(taskList.size());
        for (Task task : taskList) {
            if(task.getDelay() > 0 && task.getConExpression() != null){
                //delay와 cronExpression설정이 둘다 있을 경우
                //이러면 곤란합니다. ^^;
            }else if(task.getDelay() > 0){ //delay 설정된 경우
                taskScheduler.scheduleAtFixedRate(task, this.getFixedDelay(), task.getDelay());
                System.out.print(".");
            }else if(task.getConExpression() != null){ //cronExpression 설정된 경우
                taskScheduler.schedule(task, new CronTrigger(task.getConExpression()));
                System.out.print(".");
            }
        }
        System.out.println("["+taskList.size()+"]");
        System.out.println(">> Complete started");
    }
    
    /**
     * 현재 실행되는 서버가 Local server 인지 유무
     * @return local server이면 true
     */
    private boolean isLocalServer() throws Exception{
        if("LOCAL".equals(currenSystem)){
            return true; 
        }
        return false;
    }
    
    /**
     * 스케줄러 shutdown
     * @return shutdown된 상태라면 true
     */
    public boolean isShutdown() throws Exception{
        return this.shutdown;
    }
    
    /**
     * 지연 시간
     * @return	
     */
    private Date getFixedDelay(){
        return new Date(new Date().getTime() + 2000);
    }
    
    /**
     * restart
     */
    public void restart() throws Exception{
        this.shutdown();
        this.poolTaskScheduler.initialize();
        this.start();
    }
    
    /**
     * shutdown
     */
    public void shutdown(){
        System.out.println(">> Shutdown scheduler");
        this.poolTaskScheduler.shutdown();
        this.shutdown = true;
        System.out.println(">> Complete shutdowned");
    }

    /**
     * Scheduler의 pool size를 설정 한다.
     * @param poolSize
     * @throws Excepion
     */
    private void setPoolSize(int poolSize) throws Exception{
        //poolSize는 0이 될 수 없다(최소 1개의 값을 유지해야됨)
        if(poolSize == 0){
            throw new BaseException("시작할 Scheduler가 없습니다.");
        }
        this.poolTaskScheduler.setPoolSize(poolSize);
    }
}
